/**
 *====================================================
 * 文件名称: BeanUtils.java
 * 修订记录：
 * No    日期				作者(操作:具体内容)
 * 1.    2015年9月25日			chenxy(创建:创建文件)
 *====================================================
 * 类描述：(说明未实现或其它不应生成javadoc的内容)
 */
package com.yuexunit.finance.common.util;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;

/**
 * @ClassName: BeanUtils
 * @Description: TODO(这里用一句话描述这个类的作用)
 * @author chenxy
 * @date 2015年9月25日 上午8:40:48
 */
public class BeanUtils {

	private static final Object[] OBJECT_NULL = new Object[0];

	/**
	 * 获取指定类指定名称的属性描述符
	 * @param clazz
	 * @param propertyName
	 * @return
	 * @throws BeansException
	 */
	private static PropertyDescriptor getPropertyDescriptor(Class<?> clazz, String propertyName) throws Exception {
		CachedBeanResults cr = CachedBeanResults.forClass(clazz);
		return cr.getPropertyDescriptor(propertyName);
	}

	/**
	 * 获取指定类得所有属性描述符
	 * @param clazz
	 * @return
	 * @throws BeansException
	 */
	private static PropertyDescriptor[] getPropertyDescriptors(Class<?> clazz) throws Exception {
		CachedBeanResults cr = CachedBeanResults.forClass(clazz);
		return cr.getPropertyDescriptors();
	}

	private static boolean isIgnore(PropertyDescriptor property, String... ignores) {
		if (ignores == null || ignores.length < 1) {
			return false;
		}
		for (String ignore : ignores) {
			if (property.getName().equals(ignore)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 实现bean之间属性复制
	 * 
	 * <pre>
	 * 1.源对象属性必须和目标对象属性类型一致
	 * 2.源对象属性值不为空
	 * 3.源对象属性值为集合的不进行拷贝
	 * @param source 源对象
	 * @param target 目标对象
	 * @param ignores 忽略属性
	 */
	public static void copyProperties(Object source, Object target, String... ignores) {
		if (source == null || target == null) {
			return;
		}
		try {
			PropertyDescriptor[] tpds = getPropertyDescriptors(target.getClass());
			for (int i = 0; i < tpds.length; i++) {
				PropertyDescriptor tpd = tpds[i];
				if (isIgnore(tpd, ignores)) {
					continue;
				}
				if (tpd.getWriteMethod() == null) {
					continue;
				}
				PropertyDescriptor spd = getPropertyDescriptor(source.getClass(), tpd.getName());
				if (spd == null || !spd.getPropertyType().equals(tpd.getPropertyType()) || spd.getReadMethod() == null) {
					continue;
				}

				Method readMethod = spd.getReadMethod();
				if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
					readMethod.setAccessible(true);
				}
				Object value = readMethod.invoke(source, OBJECT_NULL);
				if (value == null) {
					continue;
				}
				// 集合类判空处理
				if (value instanceof Collection) {
					continue;
				}
				Method writeMethod = tpd.getWriteMethod();
				if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
					writeMethod.setAccessible(true);
				}
				writeMethod.invoke(target, new Object[] { value });
			}
		} catch (Throwable e) {
			throw new java.lang.IllegalArgumentException("对象复制失败...", e);
		}
	}

}
